package com.ctw.tinyservices.id.server.snowflake.factory;

import com.alibaba.druid.pool.DruidDataSource;
import com.ctw.tinyservices.id.common.config.DataSourceConfig;
import com.ctw.tinyservices.id.core.snowflake.enums.IdSnowflakeHolderTypeEnum;
import com.ctw.tinyservices.id.core.snowflake.holder.*;
import com.ctw.tinyservices.id.core.snowflake.service.IdWorkerIdService;
import com.ctw.tinyservices.id.server.snowflake.config.IdSnowflakeConfig;
import com.ctw.tinyservices.id.server.snowflake.dao.impl.IdWorkerIdDAOImpl;
import com.ctw.tinyservices.id.server.snowflake.service.IdWorkerIdServiceImpl;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

/**
 * @author TongWei.Chen 2022/4/11 14:04
 *
 * IdSnowflake Holder方式工厂
 **/
public class IdSnowflakeHolderFactory {

    private IdSnowflakeHolderFactory() {}

    private static class SingletonHolder {
        private static final IdSnowflakeHolderFactory INSTANCE = new IdSnowflakeHolderFactory();
    }

    public static final IdSnowflakeHolderFactory getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public AbstractIdSnowflakeHolder getIdSnowflakeHolder(IdSnowflakeConfig idSnowflakeConfig) {
        AbstractIdSnowflakeHolder instance;
        switch (IdSnowflakeHolderTypeEnum.valueOf(idSnowflakeConfig.getMode())) {
            case MYSQL:
                DruidDataSource druidDataSource = DataSourceConfig.getInstance().getDruidDataSource();
                IdWorkerIdService workerIdService = new IdWorkerIdServiceImpl(new IdWorkerIdDAOImpl(new JdbcTemplate(druidDataSource), new DataSourceTransactionManager(druidDataSource)));
                instance = MySQLIdSnowflakeHolder.getInstance(idSnowflakeConfig.getPort(), workerIdService);
                break;
            case ZOOKEEPER:
                instance = ZookeeperIdSnowflakeHolder.getInstance(idSnowflakeConfig.getPort(), idSnowflakeConfig.getZkConnectionAddr());
                break;
            case RECYCLABLE_ZOOKEEPER:
                instance = RecyclableZookeeperIdSnowflakeHolder.getInstance(idSnowflakeConfig.getPort(), idSnowflakeConfig.getZkConnectionAddr());
                break;
            case LOCAL:
            default:
                instance = LocalFileIdSnowflakeHolder.getInstance(idSnowflakeConfig.getPort());
                break;
        }
        return instance;
    }
}
